import java.util.ArrayList;


public class Board {
	
	static byte EMPTY = 1 << 0;
	static byte WALL = 1 << 1;
	static byte GOAL = 1 << 2;
	static byte BOX =  1 << 3;
	static byte PLAYER = 1 << 4;

	private int numRows;
	private int numColumns;
	// first dimension is y , second x
	private byte [][] data;
	private int numGoals;
	
	
	//build a board with his size
	Board (int lNumRows, int lNumColumns, ArrayList<String> inputData){
		numRows = lNumRows;
		numColumns = lNumColumns;
		data = new byte[lNumRows][lNumColumns];
		this.numGoals = 0;
		for (int i=0;i<lNumRows;i++){
        	for (int j=0;j<lNumColumns;j++){
        		char ij = inputData.get(i).charAt(j);
        		if ( ij == ' '){
        			setData(i, j, Board.EMPTY); 
        		} else if (ij == '#'){
        			setData(i, j, Board.WALL); 
        		} else if (ij == '$'){
        			setData(i, j, Board.EMPTY );
        		} else if (ij == '.'){
        			setData(i, j, Board.GOAL);
        			this.numGoals++;
        		} else if (ij == '+'){
        			setData(i, j, Board.GOAL);
        			this.numGoals++;
        		} else if (ij == '@'){
        			setData(i, j, Board.EMPTY);
        		} else if (ij == '*'){
        			setData(i, j, Board.GOAL);
        		} 
        	}
        }
	}
	
	Board (int i, int j){
		numRows = i;
		numColumns = j;
		data = new byte[i][j];
		this.numGoals = 0;
		for (int k=0;k<this.numRows;k++){
        	for (int l=0;l<this.numColumns;l++){
        		byte ij = data[k][l];
        		if ((ij&Board.GOAL) !=0) this.numGoals++;
        	} 
        }
	}
	
	
	public Board (Board b){
		numRows = b.numRows;
		numColumns = b.numColumns;
		
		for (int i=0;i<b.numRows;i++){
			for (int j=0; j<b.numColumns; j++){
				data[i][j]=b.getData(i, j);
			}
		}
		numGoals=b.numGoals;
	}
	

	//return the number of rows
	public int getNumRows(){
		return numRows;
	}
	
	//return the number of columns
	public int getNumColumns(){
		return numColumns;
	}
	
	//set the x,y data
	public void setData(int i, int j, byte value){
		data[i][j] = value;
	}
	
	//return the x,y data
	public byte getData(int i, int j){
		return data[i][j];
	}
	
	public void setData(Position p, byte value){
		data[p.getI()][p.getJ()] = value;
	}
	
	public byte getData(Position p){
		return data[p.getI()][p.getJ()];
	}
	
	public String toString(){
		String re =" ";
		for ( int x = 0 ; x < numColumns; x++){
			re+=x+" ";
		}
		re+="\n";
		for ( int i = 0 ; i < numRows ; i++){
			re+=i;
			for ( int j = 0; j < numColumns ; j++){
				if ( data[i][j] == Board.EMPTY){
					re+= "  ";
				}else if ( data[i][j] == Board.WALL){
					re+= "# ";
				}else if ( data[i][j] == Board.BOX || data[i][j] == ( Board.BOX | Board.EMPTY)){
					re+= "$ ";
				}else if ( data[i][j] == Board.PLAYER || data[i][j] == ( Board.PLAYER | Board.EMPTY)){
					re+= "@ ";
				}else if ( data[i][j] == Board.GOAL){
					re+= ". ";
				}else if ( data[i][j] == ( Board.GOAL | Board.BOX)){
					re+= "* ";
				}else if ( data[i][j] == ( Board.GOAL | Board.PLAYER)){
					re+= "+ ";
				}else{
					re+= data[i][j]+" ";
				}
			}
			re+= "\n";
		}
		return re;
	}
	
	public static String toString(byte[][] board, int numRows, int numColumns){
		String re =" ";
		for ( int i = 0 ; i < numColumns; i++){
			re+=i+" ";
		}
		re+="\n";
		for ( int i = 0 ; i < numRows ; i++){
			re+=i;
			for ( int j = 0; j < numColumns ; j++){
				if ( board[i][j] == Board.EMPTY){
					re+= "  ";
				}else if ( board[i][j] == Board.WALL){
					re+= "# ";
				}else if ( board[i][j] == Board.BOX || board[i][j] == ( Board.BOX | Board.EMPTY)){
					re+= "$ ";
				}else if ( board[i][j] == Board.PLAYER || board[i][j] == ( Board.PLAYER | Board.EMPTY)){
					re+= "@ ";
				}else if ( board[i][j] == ( Board.GOAL | Board.BOX)){
					re+= "* ";
				}else if ( board[i][j] == ( Board.GOAL | Board.PLAYER)){
					re+= "+ ";
				}else if ( board[i][j] == Board.GOAL){
					re+= ". ";
				}else{
					re+= board[i][j]+" ";
				}
			}
			re+= "\n";
		}
		return re;
	}
		
	public boolean isFinished(PlayerNBoxes pnb){
		for ( Position box: pnb.getBoxes()){
			if ( data[box.getI()][box.getJ()] != GOAL){
				return false;
			}
		}
		return true;
	}
	
	public void updateBoard(PlayerNBoxes pnb)
	{
		
		
	 	
	}

	
//	public Board moveBoard(Move m) throws CloneNotSupportedException{
//		Board b = (Board) this.clone();
//		b.setData(m.getStart(), Board.EMPTY);
//		b.setData(m.getEnd(), (byte)(Board.BOX | Board.EMPTY));
//		return b;
//	}
//	
//	public Board clone(){
//		Board b = new Board(this.getNumRows(),this.getNumColumns());
//		for (int i=0;i<this.getNumRows();i++)
//			for (int j=0;j<this.getNumColumns();j++)
//				b.setData(i, j, this.getData(i, j));
//		return b;
//	}
	 	
}
